package com.icloud.common.web.aspect;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import com.icloud.common.core.api.ResultCode;
import com.icloud.common.core.constant.AuthConstant;
import com.icloud.common.web.annotation.Permission;
import com.icloud.common.web.domain.UserDto;
import com.icloud.common.web.exception.ApiException;
import com.icloud.common.web.util.HttpUtil;
import com.nimbusds.jose.JWSObject;
import com.icloud.system.api.feign.AdminPermissionFeignClient;
import lombok.AllArgsConstructor;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;

import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;
import java.util.*;

@Aspect
@Component
@AllArgsConstructor
public class CheckPermissionAop {
    private final HttpServletRequest request;
    private final AdminPermissionFeignClient adminPermissionFeignClient;

    private final static Integer IS_ADMIN = 0;

    //@Pointcut("@annotation(com.icloud.common.web.annotation.Permission)")
    public void annotationPermissionCheckCut() {

    }

    /**
     * 权限检测处理
     */
    //@Around("annotationPermissionCheckCut()")
    public Object permissionCheck(ProceedingJoinPoint joinPoint) throws Throwable {
        //从切面织入点处通过反射机制获取织入点处的方法
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        //获取切入点所在的方法
        Method method = signature.getMethod();
        //获取自定义注解CheckPermission
        Permission annotation = method.getAnnotation(Permission.class);
        //注解值
        String[] permissionTag = annotation.value();
        //从token中获取用户信息
        String token = request.getHeader(AuthConstant.JWT_TOKEN_HEADER);
        if (StrUtil.isEmpty(token)) {
            throw new ApiException(ResultCode.UNAUTHORIZED);
        }
        String realToken = token.replace(AuthConstant.JWT_TOKEN_PREFIX, "");
        JWSObject jwsObject = JWSObject.parse(realToken);
        String userStr = jwsObject.getPayload().toString();
        UserDto userDto = JSONUtil.toBean(userStr, UserDto.class);

        //如果是主账号，不需要经过权限认证
        if(userDto.getUsername().equals("admin")) {
            return joinPoint.proceed();
        }
        //根据权限标识获取redis缓存的权限角色数据
        Map<Object, Object> permissionRolesMap = HttpUtil.getFeignData(adminPermissionFeignClient.getPermissionRolesMap());
        if(permissionRolesMap == null || CollUtil.isEmpty(permissionRolesMap)) {
            throw new ApiException(ResultCode.FORBIDDEN);
        }
        //根据数据获取指定权限对应的所有角色数据
        Iterator<Object> iterator = permissionRolesMap.keySet().iterator();
        List<String> authorities = new ArrayList<>();
        while (iterator.hasNext()) {
            String pattern = (String) iterator.next();
            if (Arrays.asList(permissionTag).contains(pattern)) {
                authorities.addAll(Convert.toList(String.class, permissionRolesMap.get(pattern)));
            }
        }
        //如果权限对应的角色集合和用户拥有的角色集合存在交集，表示有相关权限
        List<String> intersectionList = (List<String>) CollectionUtil.intersection(userDto.getRoles(), authorities);
        if(CollUtil.isNotEmpty(intersectionList)) {
            return joinPoint.proceed();
        }else {
            throw new ApiException(ResultCode.FORBIDDEN);
        }
    }
}
